<template>
    <section class="camera-video-container" ref="cameraVideoContainer">
        <video @canplay="play" @ended="ended" class="local-camera-video" ref="localCameraVideo"></video>
        <video @canplay="play" @ended="ended" v-show="state.showRemoteCameraVideo" class="remote-camera-video"
            ref="remoteCameraVideo"></video>
    </section>

    <nut-sticky v-if="state.showHangUpButton" bottom="30" position="bottom">
        <nut-button @click="hangUp" block type="primary">挂断</nut-button>
    </nut-sticky>
</template>

<script setup>
import { onMounted, getCurrentInstance, nextTick, reactive, onBeforeUnmount, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import { Toast } from "@nutui/nutui";

const localCameraVideo = ref();
const remoteCameraVideo = ref();

const route = useRoute();
const router = useRouter();
const store = useStore();
const currentInstance = getCurrentInstance();

const state = reactive({
    showRemoteCameraVideo: false,
    showHangUpButton: false,
    localCameraStream: undefined,
    call: undefined
});

onMounted(() => {
    resizeCameraVideoContainer();
    getUserMedia({ audio: false, video: true });
    locadLocalCamera();
    establishVideoCallConnection();
});

onBeforeUnmount(() => {
    releaseResources();
});

function hangUp() {
    store.state.dataConnection.callerDataConnection.send({
        operationType: store.state.dataConnection.operationType.typeEnumeration.hangUp,
        peerId: store.state.videoCall.localPeer.id
    });
    releaseResources();
    router.back();
}

function establishVideoCallConnection() {
    console.log("establishVideoCallConnection");
    if (store.state.videoCall.typeEnumeration.call === parseInt(route.query.videoCallType)) {
        //获取到本地流
        state.localCameraStream.then(localCameraStream => {
            let toast = Toast.loading("正在呼叫对方...", { duration: 0 });
            const dataConnection = store.state.videoCall.localPeer.connect(route.query.remotePeerId);
            dataConnection.on("open", () => {
                dataConnection.on("data", data => {
                    if (data.operationType) {
                        if (data.operationType === store.state.dataConnection.operationType.typeEnumeration.agreeCall) {
                            Toast.hide(toast.id);
                            toast = Toast.loading("正在连接...", { duration: 0 });
                            state.call = store.state.videoCall.localPeer.call(route.query.remotePeerId, localCameraStream);

                            state.call.on("stream", remoteCameraStream => {
                                state.showRemoteCameraVideo = true;
                                nextTick(() => {
                                    console.log(remoteCameraVideo.value);
                                    remoteCameraVideo.value.srcObject = remoteCameraStream;
                                    Toast.hide(toast.id);
                                    Toast.success("已连接");
                                });
                            });
                        } else if (data.operationType === store.state.dataConnection.operationType.typeEnumeration.rejectCall) {
                            Toast.hide(toast.id);
                            Toast.warn("对方拒绝了您的视频通话请求");
                            hangUp();
                        }
                    }
                });

                //数据连接建立成功之后立即发送通话请求
                dataConnection.send({
                    operationType: store.state.dataConnection.operationType.typeEnumeration.callRequest,
                    peerId: store.state.videoCall.localPeer.id
                });
            });
        });
    } else if (store.state.videoCall.typeEnumeration.answer === parseInt(route.query.videoCallType)) {
        let toast = Toast.loading("正在等待对方连接...", { duration: 0 });
        store.state.videoCall.localPeer.on("call", mediaConnection => {
            state.localCameraStream.then(localCameraStream => {
                mediaConnection.answer(localCameraStream);
                mediaConnection.on("stream", remoteCameraStream => {
                    if (!state.showRemoteCameraVideo) {
                        state.showRemoteCameraVideo = true;
                        nextTick(() => {
                            console.log(Date.now());
                            console.log(remoteCameraStream);
                            console.log(remoteCameraVideo.value);
                            remoteCameraVideo.value.srcObject = remoteCameraStream;
                            Toast.hide(toast.id);
                            Toast.success("已连接");
                        });
                    }
                });
            });
        });
    }
}

function locadLocalCamera() {
    state.localCameraStream.then(localCameraStream => {
        console.log(localCameraStream);
        console.log(localCameraVideo.value);
        localCameraVideo.value.srcObject = localCameraStream;
        // currentInstance.refs.localCameraVideo.play();
        nextTick(() => {
            state.showHangUpButton = true;
        });
    });
}

function play(event) {
    event.target.play();
}

function releaseResources() {
    if (store.state.videoCall.typeEnumeration.call === parseInt(route.query.videoCallType)) {
        if (state.call) {
            state.call.close();
        }
    } else if (store.state.videoCall.typeEnumeration.answer === parseInt(route.query.videoCallType)) {
        if (store.state.videoCall.callerMediaConnection) {
            store.state.videoCall.callerMediaConnection.close();
        }
    }

    if (state.localCameraStream) {
        state.localCameraStream.then(localCameraStream => {
            for (let track of localCameraStream.getTracks()) {
                track.stop();
            }
        });
    }
}

function resizeCameraVideoContainer() {
    const screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    const margin = parseFloat(document.body.style.margin ? document.body.style.margin : getComputedStyle(document.body, false).margin);
    currentInstance.refs.cameraVideoContainer.style.width = `${screenWidth - (margin * 2)}px`;
    currentInstance.refs.cameraVideoContainer.style.height = `${screenHeight - (margin * 2)}px`;
}

function getUserMedia(constrains) {
    let localCameraStream;
    if (window.navigator.mediaDevices.getUserMedia) {
        localCameraStream = window.navigator.mediaDevices.getUserMedia(constrains);
    } else if (window.navigator.webkitGetUserMedia) {
        localCameraStream = window.navigator.webkitGetUserMedia(constrains);
    } else if (window.navigator.mozGetUserMedia) {
        localCameraStream = window.navigator.mozGetUserMedia(constrains);
    } else if (window.navigator.getUserMedia) {
        localCameraStream = window.navigator.getUserMedia(constrains);
    }
    state.localCameraStream = localCameraStream;
}

</script>


<style lang="scss" scoped>
.camera-video-container {
    position: relative;

    .local-camera-video {
        width: 100%;
        height: 100%;
    }

    .remote-camera-video {
        position: absolute;
        z-index: 99;
        right: 0;
        width: 40%;
    }
}

video {
    border-radius: .625rem;
}
</style>